<!-- HTML header for doxygen 1.8.6-->
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta http-equiv="Content-Type" content="text/xhtml;charset=UTF-8"/>
<meta http-equiv="X-UA-Compatible" content="IE=9"/>
<meta name="generator" content="Doxygen 1.8.13"/>
<title>OpenCV: Decode Gray code pattern tutorial</title>
<link href="../../opencv.ico" rel="shortcut icon" type="image/x-icon" />
<link href="../../tabs.css" rel="stylesheet" type="text/css"/>
<script type="text/javascript" src="../../jquery.js"></script>
<script type="text/javascript" src="../../dynsections.js"></script>
<script type="text/javascript" src="../../tutorial-utils.js"></script>
<link href="../../search/search.css" rel="stylesheet" type="text/css"/>
<script type="text/javascript" src="../../search/searchdata.js"></script>
<script type="text/javascript" src="../../search/search.js"></script>
<script type="text/x-mathjax-config">
  MathJax.Hub.Config({
    extensions: ["tex2jax.js", "TeX/AMSmath.js", "TeX/AMSsymbols.js"],
    jax: ["input/TeX","output/HTML-CSS"],
});
//<![CDATA[
MathJax.Hub.Config(
{
  TeX: {
      Macros: {
          matTT: [ "\\[ \\left|\\begin{array}{ccc} #1 & #2 & #3\\\\ #4 & #5 & #6\\\\ #7 & #8 & #9 \\end{array}\\right| \\]", 9],
          fork: ["\\left\\{ \\begin{array}{l l} #1 & \\mbox{#2}\\\\ #3 & \\mbox{#4}\\\\ \\end{array} \\right.", 4],
          forkthree: ["\\left\\{ \\begin{array}{l l} #1 & \\mbox{#2}\\\\ #3 & \\mbox{#4}\\\\ #5 & \\mbox{#6}\\\\ \\end{array} \\right.", 6],
          forkfour: ["\\left\\{ \\begin{array}{l l} #1 & \\mbox{#2}\\\\ #3 & \\mbox{#4}\\\\ #5 & \\mbox{#6}\\\\ #7 & \\mbox{#8}\\\\ \\end{array} \\right.", 8],
          vecthree: ["\\begin{bmatrix} #1\\\\ #2\\\\ #3 \\end{bmatrix}", 3],
          vecthreethree: ["\\begin{bmatrix} #1 & #2 & #3\\\\ #4 & #5 & #6\\\\ #7 & #8 & #9 \\end{bmatrix}", 9],
          cameramatrix: ["#1 = \\begin{bmatrix} f_x & 0 & c_x\\\\ 0 & f_y & c_y\\\\ 0 & 0 & 1 \\end{bmatrix}", 1],
          distcoeffs: ["(k_1, k_2, p_1, p_2[, k_3[, k_4, k_5, k_6 [, s_1, s_2, s_3, s_4[, \\tau_x, \\tau_y]]]]) \\text{ of 4, 5, 8, 12 or 14 elements}"],
          distcoeffsfisheye: ["(k_1, k_2, k_3, k_4)"],
          hdotsfor: ["\\dots", 1],
          mathbbm: ["\\mathbb{#1}", 1],
          bordermatrix: ["\\matrix{#1}", 1]
      }
  }
}
);
//]]>
</script><script type="text/javascript" src="https://cdnjs.cloudflare.com/ajax/libs/mathjax/2.7.0/MathJax.js"></script>
<link href="../../doxygen.css" rel="stylesheet" type="text/css" />
<link href="../../stylesheet.css" rel="stylesheet" type="text/css"/>
</head>
<body>
<div id="top"><!-- do not remove this div, it is closed by doxygen! -->
<div id="titlearea">
<!--#include virtual="/google-search.html"-->
<table cellspacing="0" cellpadding="0">
 <tbody>
 <tr style="height: 56px;">
  <td id="projectlogo"><img alt="Logo" src="../../opencv-logo-small.png"/></td>
  <td style="padding-left: 0.5em;">
   <div id="projectname">OpenCV
   &#160;<span id="projectnumber">4.5.2</span>
   </div>
   <div id="projectbrief">Open Source Computer Vision</div>
  </td>
 </tr>
 </tbody>
</table>
</div>
<!-- end header part -->
<!-- Generated by Doxygen 1.8.13 -->
<script type="text/javascript">
var searchBox = new SearchBox("searchBox", "../../search",false,'Search');
</script>
<script type="text/javascript" src="../../menudata.js"></script>
<script type="text/javascript" src="../../menu.js"></script>
<script type="text/javascript">
$(function() {
  initMenu('../../',true,false,'search.php','Search');
  $(document).ready(function() { init_search(); });
});
</script>
<div id="main-nav"></div>
<!-- window showing the filter options -->
<div id="MSearchSelectWindow"
     onmouseover="return searchBox.OnSearchSelectShow()"
     onmouseout="return searchBox.OnSearchSelectHide()"
     onkeydown="return searchBox.OnSearchSelectKey(event)">
</div>

<!-- iframe showing the search results (closed by default) -->
<div id="MSearchResultsWindow">
<iframe src="javascript:void(0)" frameborder="0" 
        name="MSearchResults" id="MSearchResults">
</iframe>
</div>

<div id="nav-path" class="navpath">
  <ul>
<li class="navelem"><a class="el" href="../../d3/d81/tutorial_contrib_root.html">Tutorials for contrib modules</a></li><li class="navelem"><a class="el" href="../../d3/d81/tutorial_structured_light.html">Structured Light tutorials</a></li>  </ul>
</div>
</div><!-- top -->
<div class="header">
  <div class="headertitle">
<div class="title">Decode Gray code pattern tutorial </div>  </div>
</div><!--header-->
<div class="contents">
<div class="textblock"><h2>Goal </h2>
<p>In this tutorial you will learn how to use the <em>GrayCodePattern</em> class to:</p>
<ul>
<li>Decode a previously acquired Gray code pattern.</li>
<li>Generate a disparity map.</li>
<li>Generate a pointcloud.</li>
</ul>
<h2>Code </h2>
<div class="fragment"><div class="line"><span class="comment">/*M///////////////////////////////////////////////////////////////////////////////////////</span></div><div class="line"><span class="comment"> //</span></div><div class="line"><span class="comment"> //  IMPORTANT: READ BEFORE DOWNLOADING, COPYING, INSTALLING OR USING.</span></div><div class="line"><span class="comment"> //</span></div><div class="line"><span class="comment"> //  By downloading, copying, installing or using the software you agree to this license.</span></div><div class="line"><span class="comment"> //  If you do not agree to this license, do not download, install,</span></div><div class="line"><span class="comment"> //  copy or use the software.</span></div><div class="line"><span class="comment"> //</span></div><div class="line"><span class="comment"> //</span></div><div class="line"><span class="comment"> //                           License Agreement</span></div><div class="line"><span class="comment"> //                For Open Source Computer Vision Library</span></div><div class="line"><span class="comment"> //</span></div><div class="line"><span class="comment"> // Copyright (C) 2015, OpenCV Foundation, all rights reserved.</span></div><div class="line"><span class="comment"> // Third party copyrights are property of their respective owners.</span></div><div class="line"><span class="comment"> //</span></div><div class="line"><span class="comment"> // Redistribution and use in source and binary forms, with or without modification,</span></div><div class="line"><span class="comment"> // are permitted provided that the following conditions are met:</span></div><div class="line"><span class="comment"> //</span></div><div class="line"><span class="comment"> //   * Redistribution&#39;s of source code must retain the above copyright notice,</span></div><div class="line"><span class="comment"> //     this list of conditions and the following disclaimer.</span></div><div class="line"><span class="comment"> //</span></div><div class="line"><span class="comment"> //   * Redistribution&#39;s in binary form must reproduce the above copyright notice,</span></div><div class="line"><span class="comment"> //     this list of conditions and the following disclaimer in the documentation</span></div><div class="line"><span class="comment"> //     and/or other materials provided with the distribution.</span></div><div class="line"><span class="comment"> //</span></div><div class="line"><span class="comment"> //   * The name of the copyright holders may not be used to endorse or promote products</span></div><div class="line"><span class="comment"> //     derived from this software without specific prior written permission.</span></div><div class="line"><span class="comment"> //</span></div><div class="line"><span class="comment"> // This software is provided by the copyright holders and contributors &quot;as is&quot; and</span></div><div class="line"><span class="comment"> // any express or implied warranties, including, but not limited to, the implied</span></div><div class="line"><span class="comment"> // warranties of merchantability and fitness for a particular purpose are disclaimed.</span></div><div class="line"><span class="comment"> // In no event shall the Intel Corporation or contributors be liable for any direct,</span></div><div class="line"><span class="comment"> // indirect, incidental, special, exemplary, or consequential damages</span></div><div class="line"><span class="comment"> // (including, but not limited to, procurement of substitute goods or services;</span></div><div class="line"><span class="comment"> // loss of use, data, or profits; or business interruption) however caused</span></div><div class="line"><span class="comment"> // and on any theory of liability, whether in contract, strict liability,</span></div><div class="line"><span class="comment"> // or tort (including negligence or otherwise) arising in any way out of</span></div><div class="line"><span class="comment"> // the use of this software, even if advised of the possibility of such damage.</span></div><div class="line"><span class="comment"> //</span></div><div class="line"><span class="comment"> //M*/</span></div><div class="line"></div><div class="line"><span class="preprocessor">#include &lt;iostream&gt;</span></div><div class="line"><span class="preprocessor">#include &lt;<a class="code" href="../../d0/d9c/core_2include_2opencv2_2core_8hpp.html">opencv2/core.hpp</a>&gt;</span></div><div class="line"><span class="preprocessor">#include &lt;<a class="code" href="../../d4/dd5/highgui_8hpp.html">opencv2/highgui.hpp</a>&gt;</span></div><div class="line"><span class="preprocessor">#include &lt;<a class="code" href="../../d2/d28/calib3d_8hpp.html">opencv2/calib3d.hpp</a>&gt;</span></div><div class="line"><span class="preprocessor">#include &lt;<a class="code" href="../../d1/d4f/imgproc_2include_2opencv2_2imgproc_8hpp.html">opencv2/imgproc.hpp</a>&gt;</span></div><div class="line"><span class="preprocessor">#include &lt;<a class="code" href="../../d3/d23/structured__light_8hpp.html">opencv2/structured_light.hpp</a>&gt;</span></div><div class="line"><span class="preprocessor">#include &lt;opencv2/opencv_modules.hpp&gt;</span></div><div class="line"></div><div class="line"><span class="comment">// (if you did not build the opencv_viz module, you will only see the disparity images)</span></div><div class="line"><span class="preprocessor">#ifdef HAVE_OPENCV_VIZ</span></div><div class="line"><span class="preprocessor">#include &lt;<a class="code" href="../../d0/d7e/viz_8hpp.html">opencv2/viz.hpp</a>&gt;</span></div><div class="line"><span class="preprocessor">#endif</span></div><div class="line"></div><div class="line"><span class="keyword">using namespace </span>std;</div><div class="line"><span class="keyword">using namespace </span><a class="code" href="../../d2/d75/namespacecv.html">cv</a>;</div><div class="line"></div><div class="line"><span class="keyword">static</span> <span class="keyword">const</span> <span class="keywordtype">char</span>* keys =</div><div class="line">{ <span class="stringliteral">&quot;{@images_list | | Image list where the captured pattern images are saved}&quot;</span></div><div class="line">    <span class="stringliteral">&quot;{@calib_param_path     | | Calibration_parameters            }&quot;</span></div><div class="line">    <span class="stringliteral">&quot;{@proj_width      | | The projector width used to acquire the pattern          }&quot;</span></div><div class="line">    <span class="stringliteral">&quot;{@proj_height     | | The projector height used to acquire the pattern}&quot;</span></div><div class="line">    <span class="stringliteral">&quot;{@white_thresh     | | The white threshold height (optional)}&quot;</span></div><div class="line">    <span class="stringliteral">&quot;{@black_thresh     | | The black threshold (optional)}&quot;</span> };</div><div class="line"></div><div class="line"><span class="keyword">static</span> <span class="keywordtype">void</span> help()</div><div class="line">{</div><div class="line">  cout &lt;&lt; <span class="stringliteral">&quot;\nThis example shows how to use the \&quot;Structured Light module\&quot; to decode a previously acquired gray code pattern, generating a pointcloud&quot;</span></div><div class="line">        <span class="stringliteral">&quot;\nCall:\n&quot;</span></div><div class="line">        <span class="stringliteral">&quot;./example_structured_light_pointcloud &lt;images_list&gt; &lt;calib_param_path&gt; &lt;proj_width&gt; &lt;proj_height&gt; &lt;white_thresh&gt; &lt;black_thresh&gt;\n&quot;</span></div><div class="line">        &lt;&lt; endl;</div><div class="line">}</div><div class="line"></div><div class="line"><span class="keyword">static</span> <span class="keywordtype">bool</span> readStringList( <span class="keyword">const</span> <span class="keywordtype">string</span>&amp; filename, vector&lt;string&gt;&amp; l )</div><div class="line">{</div><div class="line">  l.resize( 0 );</div><div class="line">  <a class="code" href="../../da/d56/classcv_1_1FileStorage.html">FileStorage</a> fs( filename, FileStorage::READ );</div><div class="line">  <span class="keywordflow">if</span>( !fs.<a class="code" href="../../da/d56/classcv_1_1FileStorage.html#aa952c31f4e632595cd5ac107913f4fd1">isOpened</a>() )</div><div class="line">  {</div><div class="line">    cerr &lt;&lt; <span class="stringliteral">&quot;failed to open &quot;</span> &lt;&lt; filename &lt;&lt; endl;</div><div class="line">    <span class="keywordflow">return</span> <span class="keyword">false</span>;</div><div class="line">  }</div><div class="line">  <a class="code" href="../../de/dd9/classcv_1_1FileNode.html">FileNode</a> n = fs.<a class="code" href="../../da/d56/classcv_1_1FileStorage.html#a7153604af73ca7de43b977eedd1bbe09">getFirstTopLevelNode</a>();</div><div class="line">  <span class="keywordflow">if</span>( n.<a class="code" href="../../de/dd9/classcv_1_1FileNode.html#ad0fd448e25719a94320ebe574b87f997">type</a>() != FileNode::SEQ )</div><div class="line">  {</div><div class="line">    cerr &lt;&lt; <span class="stringliteral">&quot;cam 1 images are not a sequence! FAIL&quot;</span> &lt;&lt; endl;</div><div class="line">    <span class="keywordflow">return</span> <span class="keyword">false</span>;</div><div class="line">  }</div><div class="line"></div><div class="line">  <a class="code" href="../../d7/d4e/classcv_1_1FileNodeIterator.html">FileNodeIterator</a> it = n.<a class="code" href="../../de/dd9/classcv_1_1FileNode.html#a0f299820227506079f5b9013dd8c3558">begin</a>(), it_end = n.<a class="code" href="../../de/dd9/classcv_1_1FileNode.html#a58b033e34726eb73f0238a1bfbe0c8e9">end</a>();</div><div class="line">  <span class="keywordflow">for</span>( ; it != it_end; ++it )</div><div class="line">  {</div><div class="line">    l.push_back( ( <span class="keywordtype">string</span> ) *it );</div><div class="line">  }</div><div class="line"></div><div class="line">  n = fs[<span class="stringliteral">&quot;cam2&quot;</span>];</div><div class="line">  <span class="keywordflow">if</span>( n.<a class="code" href="../../de/dd9/classcv_1_1FileNode.html#ad0fd448e25719a94320ebe574b87f997">type</a>() != FileNode::SEQ )</div><div class="line">  {</div><div class="line">    cerr &lt;&lt; <span class="stringliteral">&quot;cam 2 images are not a sequence! FAIL&quot;</span> &lt;&lt; endl;</div><div class="line">    <span class="keywordflow">return</span> <span class="keyword">false</span>;</div><div class="line">  }</div><div class="line"></div><div class="line">  it = n.<a class="code" href="../../de/dd9/classcv_1_1FileNode.html#a0f299820227506079f5b9013dd8c3558">begin</a>(), it_end = n.<a class="code" href="../../de/dd9/classcv_1_1FileNode.html#a58b033e34726eb73f0238a1bfbe0c8e9">end</a>();</div><div class="line">  <span class="keywordflow">for</span>( ; it != it_end; ++it )</div><div class="line">  {</div><div class="line">    l.push_back( ( <span class="keywordtype">string</span> ) *it );</div><div class="line">  }</div><div class="line"></div><div class="line">  <span class="keywordflow">if</span>( l.size() % 2 != 0 )</div><div class="line">  {</div><div class="line">    cout &lt;&lt; <span class="stringliteral">&quot;Error: the image list contains odd (non-even) number of elements\n&quot;</span>;</div><div class="line">    <span class="keywordflow">return</span> <span class="keyword">false</span>;</div><div class="line">  }</div><div class="line">  <span class="keywordflow">return</span> <span class="keyword">true</span>;</div><div class="line">}</div><div class="line"></div><div class="line"><span class="keywordtype">int</span> main( <span class="keywordtype">int</span> argc, <span class="keywordtype">char</span>** argv )</div><div class="line">{</div><div class="line">  <a class="code" href="../../d3/d4d/structcv_1_1structured__light_1_1GrayCodePattern_1_1Params.html">structured_light::GrayCodePattern::Params</a> <a class="code" href="../../d1/dae/namespacecv_1_1gapi_1_1ie.html#a3ab1729bcaf2d08e30dd2bc645410908">params</a>;</div><div class="line">  <a class="code" href="../../d0/d2e/classcv_1_1CommandLineParser.html">CommandLineParser</a> parser( argc, argv, keys );</div><div class="line">  <a class="code" href="../../dc/d84/group__core__basic.html#ga1f6634802eeadfd7245bc75cf3e216c2">String</a> images_file = parser.get&lt;<a class="code" href="../../dc/d84/group__core__basic.html#ga1f6634802eeadfd7245bc75cf3e216c2">String</a>&gt;( 0 );</div><div class="line">  <a class="code" href="../../dc/d84/group__core__basic.html#ga1f6634802eeadfd7245bc75cf3e216c2">String</a> calib_file = parser.get&lt;<a class="code" href="../../dc/d84/group__core__basic.html#ga1f6634802eeadfd7245bc75cf3e216c2">String</a>&gt;( 1 );</div><div class="line"></div><div class="line">  params.<a class="code" href="../../d3/d4d/structcv_1_1structured__light_1_1GrayCodePattern_1_1Params.html#afeaf367767fcb43529a4fa5b9c9309af">width</a> = parser.get&lt;<span class="keywordtype">int</span>&gt;( 2 );</div><div class="line">  params.<a class="code" href="../../d3/d4d/structcv_1_1structured__light_1_1GrayCodePattern_1_1Params.html#a06c9109b5a1ec886e270984b68e480e4">height</a> = parser.get&lt;<span class="keywordtype">int</span>&gt;( 3 );</div><div class="line"></div><div class="line">  <span class="keywordflow">if</span>( images_file.empty() || calib_file.empty() || params.<a class="code" href="../../d3/d4d/structcv_1_1structured__light_1_1GrayCodePattern_1_1Params.html#afeaf367767fcb43529a4fa5b9c9309af">width</a> &lt; 1 || params.<a class="code" href="../../d3/d4d/structcv_1_1structured__light_1_1GrayCodePattern_1_1Params.html#a06c9109b5a1ec886e270984b68e480e4">height</a> &lt; 1 || argc &lt; 5 || argc &gt; 7 )</div><div class="line">  {</div><div class="line">    help();</div><div class="line">    <span class="keywordflow">return</span> -1;</div><div class="line">  }</div><div class="line"></div><div class="line">  <span class="comment">// Set up GraycodePattern with params</span></div><div class="line">  <a class="code" href="../../dc/d84/group__core__basic.html#ga6395ca871a678020c4a31fadf7e8cc63">Ptr&lt;structured_light::GrayCodePattern&gt;</a> graycode = structured_light::GrayCodePattern::create( params );</div><div class="line">  <span class="keywordtype">size_t</span> white_thresh = 0;</div><div class="line">  <span class="keywordtype">size_t</span> black_thresh = 0;</div><div class="line"></div><div class="line">  <span class="keywordflow">if</span>( argc == 7 )</div><div class="line">  {</div><div class="line">    <span class="comment">// If passed, setting the white and black threshold, otherwise using default values</span></div><div class="line">    white_thresh = parser.get&lt;<span class="keywordtype">unsigned</span>&gt;( 4 );</div><div class="line">    black_thresh = parser.get&lt;<span class="keywordtype">unsigned</span>&gt;( 5 );</div><div class="line"></div><div class="line">    graycode-&gt;setWhiteThreshold( white_thresh );</div><div class="line">    graycode-&gt;setBlackThreshold( black_thresh );</div><div class="line">  }</div><div class="line"></div><div class="line">  vector&lt;string&gt; imagelist;</div><div class="line">  <span class="keywordtype">bool</span> ok = readStringList( images_file, imagelist );</div><div class="line">  <span class="keywordflow">if</span>( !ok || imagelist.empty() )</div><div class="line">  {</div><div class="line">    cout &lt;&lt; <span class="stringliteral">&quot;can not open &quot;</span> &lt;&lt; images_file &lt;&lt; <span class="stringliteral">&quot; or the string list is empty&quot;</span> &lt;&lt; endl;</div><div class="line">    help();</div><div class="line">    <span class="keywordflow">return</span> -1;</div><div class="line">  }</div><div class="line"></div><div class="line">  <a class="code" href="../../da/d56/classcv_1_1FileStorage.html">FileStorage</a> fs( calib_file, FileStorage::READ );</div><div class="line">  <span class="keywordflow">if</span>( !fs.<a class="code" href="../../da/d56/classcv_1_1FileStorage.html#aa952c31f4e632595cd5ac107913f4fd1">isOpened</a>() )</div><div class="line">  {</div><div class="line">    cout &lt;&lt; <span class="stringliteral">&quot;Failed to open Calibration Data File.&quot;</span> &lt;&lt; endl;</div><div class="line">    help();</div><div class="line">    <span class="keywordflow">return</span> -1;</div><div class="line">  }</div><div class="line"></div><div class="line">  <span class="comment">// Loading calibration parameters</span></div><div class="line">  <a class="code" href="../../d3/d63/classcv_1_1Mat.html">Mat</a> cam1intrinsics, cam1distCoeffs, cam2intrinsics, cam2distCoeffs, R, T;</div><div class="line">  fs[<span class="stringliteral">&quot;cam1_intrinsics&quot;</span>] &gt;&gt; cam1intrinsics;</div><div class="line">  fs[<span class="stringliteral">&quot;cam2_intrinsics&quot;</span>] &gt;&gt; cam2intrinsics;</div><div class="line">  fs[<span class="stringliteral">&quot;cam1_distorsion&quot;</span>] &gt;&gt; cam1distCoeffs;</div><div class="line">  fs[<span class="stringliteral">&quot;cam2_distorsion&quot;</span>] &gt;&gt; cam2distCoeffs;</div><div class="line">  fs[<span class="stringliteral">&quot;R&quot;</span>] &gt;&gt; R;</div><div class="line">  fs[<span class="stringliteral">&quot;T&quot;</span>] &gt;&gt; T;</div><div class="line"></div><div class="line">  cout &lt;&lt; <span class="stringliteral">&quot;cam1intrinsics&quot;</span> &lt;&lt; endl &lt;&lt; cam1intrinsics &lt;&lt; endl;</div><div class="line">  cout &lt;&lt; <span class="stringliteral">&quot;cam1distCoeffs&quot;</span> &lt;&lt; endl &lt;&lt; cam1distCoeffs &lt;&lt; endl;</div><div class="line">  cout &lt;&lt; <span class="stringliteral">&quot;cam2intrinsics&quot;</span> &lt;&lt; endl &lt;&lt; cam2intrinsics &lt;&lt; endl;</div><div class="line">  cout &lt;&lt; <span class="stringliteral">&quot;cam2distCoeffs&quot;</span> &lt;&lt; endl &lt;&lt; cam2distCoeffs &lt;&lt; endl;</div><div class="line">  cout &lt;&lt; <span class="stringliteral">&quot;T&quot;</span> &lt;&lt; endl &lt;&lt; T &lt;&lt; endl &lt;&lt; <span class="stringliteral">&quot;R&quot;</span> &lt;&lt; endl &lt;&lt; R &lt;&lt; endl;</div><div class="line"></div><div class="line">  <span class="keywordflow">if</span>( (!R.data) || (!T.data) || (!cam1intrinsics.data) || (!cam2intrinsics.data) || (!cam1distCoeffs.data) || (!cam2distCoeffs.data) )</div><div class="line">  {</div><div class="line">    cout &lt;&lt; <span class="stringliteral">&quot;Failed to load cameras calibration parameters&quot;</span> &lt;&lt; endl;</div><div class="line">    help();</div><div class="line">    <span class="keywordflow">return</span> -1;</div><div class="line">  }</div><div class="line"></div><div class="line">  <span class="keywordtype">size_t</span> numberOfPatternImages = graycode-&gt;getNumberOfPatternImages();</div><div class="line">  vector&lt;vector&lt;Mat&gt; &gt; captured_pattern;</div><div class="line">  captured_pattern.resize( 2 );</div><div class="line">  captured_pattern[0].resize( numberOfPatternImages );</div><div class="line">  captured_pattern[1].resize( numberOfPatternImages );</div><div class="line"></div><div class="line">  <a class="code" href="../../d3/d63/classcv_1_1Mat.html">Mat</a> color = <a class="code" href="../../d4/da8/group__imgcodecs.html#ga288b8b3da0892bd651fce07b3bbd3a56">imread</a>( imagelist[numberOfPatternImages], <a class="code" href="../../d8/d6a/group__imgcodecs__flags.html#gga61d9b0126a3e57d9277ac48327799c80af660544735200cbe942eea09232eb822">IMREAD_COLOR</a> );</div><div class="line">  <a class="code" href="../../d6/d50/classcv_1_1Size__.html">Size</a> imagesSize = color.<a class="code" href="../../d3/d63/classcv_1_1Mat.html#a146f8e8dda07d1365a575ab83d9828d1">size</a>();</div><div class="line"></div><div class="line">  <span class="comment">// Stereo rectify</span></div><div class="line">  cout &lt;&lt; <span class="stringliteral">&quot;Rectifying images...&quot;</span> &lt;&lt; endl;</div><div class="line">  <a class="code" href="../../d3/d63/classcv_1_1Mat.html">Mat</a> R1, R2, P1, P2, Q;</div><div class="line">  <a class="code" href="../../d2/d44/classcv_1_1Rect__.html">Rect</a> validRoi[2];</div><div class="line">  <a class="code" href="../../d9/d0c/group__calib3d.html#ga617b1685d4059c6040827800e72ad2b6">stereoRectify</a>( cam1intrinsics, cam1distCoeffs, cam2intrinsics, cam2distCoeffs, imagesSize, R, T, R1, R2, P1, P2, Q, 0,</div><div class="line">                -1, imagesSize, &amp;validRoi[0], &amp;validRoi[1] );</div><div class="line"></div><div class="line">  <a class="code" href="../../d3/d63/classcv_1_1Mat.html">Mat</a> map1x, map1y, map2x, map2y;</div><div class="line">  <a class="code" href="../../d9/d0c/group__calib3d.html#ga7dfb72c9cf9780a347fbe3d1c47e5d5a">initUndistortRectifyMap</a>( cam1intrinsics, cam1distCoeffs, R1, P1, imagesSize, <a class="code" href="../../d1/d1b/group__core__hal__interface.html#ga32ec76240e43e4c9c7b2e2785180a7e6">CV_32FC1</a>, map1x, map1y );</div><div class="line">  <a class="code" href="../../d9/d0c/group__calib3d.html#ga7dfb72c9cf9780a347fbe3d1c47e5d5a">initUndistortRectifyMap</a>( cam2intrinsics, cam2distCoeffs, R2, P2, imagesSize, <a class="code" href="../../d1/d1b/group__core__hal__interface.html#ga32ec76240e43e4c9c7b2e2785180a7e6">CV_32FC1</a>, map2x, map2y );</div><div class="line"></div><div class="line">  <span class="comment">// Loading pattern images</span></div><div class="line">  <span class="keywordflow">for</span>( <span class="keywordtype">size_t</span> i = 0; i &lt; numberOfPatternImages; i++ )</div><div class="line">  {</div><div class="line">    captured_pattern[0][i] = <a class="code" href="../../d4/da8/group__imgcodecs.html#ga288b8b3da0892bd651fce07b3bbd3a56">imread</a>( imagelist[i], <a class="code" href="../../d8/d6a/group__imgcodecs__flags.html#gga61d9b0126a3e57d9277ac48327799c80ae29981cfc153d3b0cef5c0daeedd2125">IMREAD_GRAYSCALE</a> );</div><div class="line">    captured_pattern[1][i] = <a class="code" href="../../d4/da8/group__imgcodecs.html#ga288b8b3da0892bd651fce07b3bbd3a56">imread</a>( imagelist[i + numberOfPatternImages + 2], <a class="code" href="../../d8/d6a/group__imgcodecs__flags.html#gga61d9b0126a3e57d9277ac48327799c80ae29981cfc153d3b0cef5c0daeedd2125">IMREAD_GRAYSCALE</a> );</div><div class="line"></div><div class="line">    <span class="keywordflow">if</span>( (!captured_pattern[0][i].data) || (!captured_pattern[1][i].data) )</div><div class="line">    {</div><div class="line">      cout &lt;&lt; <span class="stringliteral">&quot;Empty images&quot;</span> &lt;&lt; endl;</div><div class="line">      help();</div><div class="line">      <span class="keywordflow">return</span> -1;</div><div class="line">    }</div><div class="line"></div><div class="line">    <a class="code" href="../../da/d54/group__imgproc__transform.html#gab75ef31ce5cdfb5c44b6da5f3b908ea4">remap</a>( captured_pattern[1][i], captured_pattern[1][i], map1x, map1y, <a class="code" href="../../da/d54/group__imgproc__transform.html#gga5bb5a1fea74ea38e1a5445ca803ff121aa5521d8e080972c762467c45f3b70e6c">INTER_NEAREST</a>, <a class="code" href="../../d2/de8/group__core__array.html#gga209f2f4869e304c82d07739337eae7c5aed2e4346047e265c8c5a6d0276dcd838">BORDER_CONSTANT</a>, <a class="code" href="../../dc/d84/group__core__basic.html#ga599fe92e910c027be274233eccad7beb">Scalar</a>() );</div><div class="line">    <a class="code" href="../../da/d54/group__imgproc__transform.html#gab75ef31ce5cdfb5c44b6da5f3b908ea4">remap</a>( captured_pattern[0][i], captured_pattern[0][i], map2x, map2y, <a class="code" href="../../da/d54/group__imgproc__transform.html#gga5bb5a1fea74ea38e1a5445ca803ff121aa5521d8e080972c762467c45f3b70e6c">INTER_NEAREST</a>, <a class="code" href="../../d2/de8/group__core__array.html#gga209f2f4869e304c82d07739337eae7c5aed2e4346047e265c8c5a6d0276dcd838">BORDER_CONSTANT</a>, <a class="code" href="../../dc/d84/group__core__basic.html#ga599fe92e910c027be274233eccad7beb">Scalar</a>() );</div><div class="line"></div><div class="line">  }</div><div class="line">  cout &lt;&lt; <span class="stringliteral">&quot;done&quot;</span> &lt;&lt; endl;</div><div class="line"></div><div class="line">  vector&lt;Mat&gt; blackImages;</div><div class="line">  vector&lt;Mat&gt; whiteImages;</div><div class="line"></div><div class="line">  blackImages.resize( 2 );</div><div class="line">  whiteImages.resize( 2 );</div><div class="line"></div><div class="line">  <span class="comment">// Loading images (all white + all black) needed for shadows computation</span></div><div class="line">  <a class="code" href="../../d8/d01/group__imgproc__color__conversions.html#ga397ae87e1288a81d2363b61574eb8cab">cvtColor</a>( color, whiteImages[0], <a class="code" href="../../d8/d01/group__imgproc__color__conversions.html#gga4e0972be5de079fed4e3a10e24ef5ef0ae50d0c66ee53e974234ac84cf51d1d4e">COLOR_RGB2GRAY</a> );</div><div class="line"></div><div class="line">  whiteImages[1] = <a class="code" href="../../d4/da8/group__imgcodecs.html#ga288b8b3da0892bd651fce07b3bbd3a56">imread</a>( imagelist[2 * numberOfPatternImages + 2], <a class="code" href="../../d8/d6a/group__imgcodecs__flags.html#gga61d9b0126a3e57d9277ac48327799c80ae29981cfc153d3b0cef5c0daeedd2125">IMREAD_GRAYSCALE</a> );</div><div class="line">  blackImages[0] = <a class="code" href="../../d4/da8/group__imgcodecs.html#ga288b8b3da0892bd651fce07b3bbd3a56">imread</a>( imagelist[numberOfPatternImages + 1], <a class="code" href="../../d8/d6a/group__imgcodecs__flags.html#gga61d9b0126a3e57d9277ac48327799c80ae29981cfc153d3b0cef5c0daeedd2125">IMREAD_GRAYSCALE</a> );</div><div class="line">  blackImages[1] = <a class="code" href="../../d4/da8/group__imgcodecs.html#ga288b8b3da0892bd651fce07b3bbd3a56">imread</a>( imagelist[2 * numberOfPatternImages + 2 + 1], <a class="code" href="../../d8/d6a/group__imgcodecs__flags.html#gga61d9b0126a3e57d9277ac48327799c80ae29981cfc153d3b0cef5c0daeedd2125">IMREAD_GRAYSCALE</a> );</div><div class="line"></div><div class="line">  <a class="code" href="../../da/d54/group__imgproc__transform.html#gab75ef31ce5cdfb5c44b6da5f3b908ea4">remap</a>( color, color, map2x, map2y, <a class="code" href="../../da/d54/group__imgproc__transform.html#gga5bb5a1fea74ea38e1a5445ca803ff121aa5521d8e080972c762467c45f3b70e6c">INTER_NEAREST</a>, <a class="code" href="../../d2/de8/group__core__array.html#gga209f2f4869e304c82d07739337eae7c5aed2e4346047e265c8c5a6d0276dcd838">BORDER_CONSTANT</a>, <a class="code" href="../../dc/d84/group__core__basic.html#ga599fe92e910c027be274233eccad7beb">Scalar</a>() );</div><div class="line"></div><div class="line">  <a class="code" href="../../da/d54/group__imgproc__transform.html#gab75ef31ce5cdfb5c44b6da5f3b908ea4">remap</a>( whiteImages[0], whiteImages[0], map2x, map2y, <a class="code" href="../../da/d54/group__imgproc__transform.html#gga5bb5a1fea74ea38e1a5445ca803ff121aa5521d8e080972c762467c45f3b70e6c">INTER_NEAREST</a>, <a class="code" href="../../d2/de8/group__core__array.html#gga209f2f4869e304c82d07739337eae7c5aed2e4346047e265c8c5a6d0276dcd838">BORDER_CONSTANT</a>, <a class="code" href="../../dc/d84/group__core__basic.html#ga599fe92e910c027be274233eccad7beb">Scalar</a>() );</div><div class="line">  <a class="code" href="../../da/d54/group__imgproc__transform.html#gab75ef31ce5cdfb5c44b6da5f3b908ea4">remap</a>( whiteImages[1], whiteImages[1], map1x, map1y, <a class="code" href="../../da/d54/group__imgproc__transform.html#gga5bb5a1fea74ea38e1a5445ca803ff121aa5521d8e080972c762467c45f3b70e6c">INTER_NEAREST</a>, <a class="code" href="../../d2/de8/group__core__array.html#gga209f2f4869e304c82d07739337eae7c5aed2e4346047e265c8c5a6d0276dcd838">BORDER_CONSTANT</a>, <a class="code" href="../../dc/d84/group__core__basic.html#ga599fe92e910c027be274233eccad7beb">Scalar</a>() );</div><div class="line"></div><div class="line">  <a class="code" href="../../da/d54/group__imgproc__transform.html#gab75ef31ce5cdfb5c44b6da5f3b908ea4">remap</a>( blackImages[0], blackImages[0], map2x, map2y, <a class="code" href="../../da/d54/group__imgproc__transform.html#gga5bb5a1fea74ea38e1a5445ca803ff121aa5521d8e080972c762467c45f3b70e6c">INTER_NEAREST</a>, <a class="code" href="../../d2/de8/group__core__array.html#gga209f2f4869e304c82d07739337eae7c5aed2e4346047e265c8c5a6d0276dcd838">BORDER_CONSTANT</a>, <a class="code" href="../../dc/d84/group__core__basic.html#ga599fe92e910c027be274233eccad7beb">Scalar</a>() );</div><div class="line">  <a class="code" href="../../da/d54/group__imgproc__transform.html#gab75ef31ce5cdfb5c44b6da5f3b908ea4">remap</a>( blackImages[1], blackImages[1], map1x, map1y, <a class="code" href="../../da/d54/group__imgproc__transform.html#gga5bb5a1fea74ea38e1a5445ca803ff121aa5521d8e080972c762467c45f3b70e6c">INTER_NEAREST</a>, <a class="code" href="../../d2/de8/group__core__array.html#gga209f2f4869e304c82d07739337eae7c5aed2e4346047e265c8c5a6d0276dcd838">BORDER_CONSTANT</a>, <a class="code" href="../../dc/d84/group__core__basic.html#ga599fe92e910c027be274233eccad7beb">Scalar</a>() );</div><div class="line"></div><div class="line">  cout &lt;&lt; endl &lt;&lt; <span class="stringliteral">&quot;Decoding pattern ...&quot;</span> &lt;&lt; endl;</div><div class="line">  <a class="code" href="../../d3/d63/classcv_1_1Mat.html">Mat</a> disparityMap;</div><div class="line">  <span class="keywordtype">bool</span> decoded = graycode-&gt;decode( captured_pattern, disparityMap, blackImages, whiteImages,</div><div class="line">                                  <a class="code" href="../../d1/d90/group__structured__light.html#ggafaa062a39adfeb3836b8730fda1a6b89a98f0a8c890dded38d226722bcdd5795c">structured_light::DECODE_3D_UNDERWORLD</a> );</div><div class="line">  <span class="keywordflow">if</span>( decoded )</div><div class="line">  {</div><div class="line">    cout &lt;&lt; endl &lt;&lt; <span class="stringliteral">&quot;pattern decoded&quot;</span> &lt;&lt; endl;</div><div class="line"></div><div class="line">    <span class="comment">// To better visualize the result, apply a colormap to the computed disparity</span></div><div class="line">    <span class="keywordtype">double</span> <a class="code" href="../../d7/dcc/group__core__utils__softfloat.html#gac48df53b8fd34b87e7b121fa8fd4c379">min</a>;</div><div class="line">    <span class="keywordtype">double</span> <a class="code" href="../../d7/dcc/group__core__utils__softfloat.html#ga78f988f6cfa6223610298cbd4f86ec66">max</a>;</div><div class="line">    <a class="code" href="../../d2/de8/group__core__array.html#ga7622c466c628a75d9ed008b42250a73f">minMaxIdx</a>(disparityMap, &amp;min, &amp;max);</div><div class="line">    <a class="code" href="../../d3/d63/classcv_1_1Mat.html">Mat</a> cm_disp, scaledDisparityMap;</div><div class="line">    cout &lt;&lt; <span class="stringliteral">&quot;disp min &quot;</span> &lt;&lt; min &lt;&lt; endl &lt;&lt; <span class="stringliteral">&quot;disp max &quot;</span> &lt;&lt; max &lt;&lt; endl;</div><div class="line">    <a class="code" href="../../d2/de8/group__core__array.html#ga3460e9c9f37b563ab9dd550c4d8c4e7d">convertScaleAbs</a>( disparityMap, scaledDisparityMap, 255 / ( max - min ) );</div><div class="line">    <a class="code" href="../../d3/d50/group__imgproc__colormap.html#gadf478a5e5ff49d8aa24e726ea6f65d15">applyColorMap</a>( scaledDisparityMap, cm_disp, <a class="code" href="../../d3/d50/group__imgproc__colormap.html#gga9a805d8262bcbe273f16be9ea2055a65ab3f207661ddf74511b002b1acda5ec09">COLORMAP_JET</a> );</div><div class="line"></div><div class="line">    <span class="comment">// Show the result</span></div><div class="line">    <a class="code" href="../../d5/df1/group__imgproc__hal__functions.html#ga2fe39d2201b12e1b961ca56b2aff9ff2">resize</a>( cm_disp, cm_disp, <a class="code" href="../../dc/d84/group__core__basic.html#ga346f563897249351a34549137c8532a0">Size</a>( 640, 480 ), 0, 0, <a class="code" href="../../da/d54/group__imgproc__transform.html#gga5bb5a1fea74ea38e1a5445ca803ff121ac00f4a8155563cdc23437fc0959da935">INTER_LINEAR_EXACT</a> );</div><div class="line">    <a class="code" href="../../d7/dfc/group__highgui.html#ga453d42fe4cb60e5723281a89973ee563">imshow</a>( <span class="stringliteral">&quot;cm disparity m&quot;</span>, cm_disp );</div><div class="line"></div><div class="line">    <span class="comment">// Compute the point cloud</span></div><div class="line">    <a class="code" href="../../d3/d63/classcv_1_1Mat.html">Mat</a> pointcloud;</div><div class="line">    disparityMap.<a class="code" href="../../d3/d63/classcv_1_1Mat.html#adf88c60c5b4980e05bb556080916978b">convertTo</a>( disparityMap, <a class="code" href="../../d1/d1b/group__core__hal__interface.html#ga32ec76240e43e4c9c7b2e2785180a7e6">CV_32FC1</a> );</div><div class="line">    <a class="code" href="../../d9/d0c/group__calib3d.html#ga1bc1152bd57d63bc524204f21fde6e02">reprojectImageTo3D</a>( disparityMap, pointcloud, Q, <span class="keyword">true</span>, -1 );</div><div class="line"></div><div class="line">    <span class="comment">// Compute a mask to remove background</span></div><div class="line">    <a class="code" href="../../d3/d63/classcv_1_1Mat.html">Mat</a> dst, thresholded_disp;</div><div class="line">    <a class="code" href="../../d7/d1b/group__imgproc__misc.html#gae8a4a146d1ca78c626a53577199e9c57">threshold</a>( scaledDisparityMap, thresholded_disp, 0, 255, <a class="code" href="../../d7/d1b/group__imgproc__misc.html#ggaa9e58d2860d4afa658ef70a9b1115576a95251923e8e22f368ffa86ba8bce87ff">THRESH_OTSU</a> + <a class="code" href="../../d7/d1b/group__imgproc__misc.html#ggaa9e58d2860d4afa658ef70a9b1115576a147222a96556ebc1d948b372bcd7ac59">THRESH_BINARY</a> );</div><div class="line">    <a class="code" href="../../d5/df1/group__imgproc__hal__functions.html#ga2fe39d2201b12e1b961ca56b2aff9ff2">resize</a>( thresholded_disp, dst, <a class="code" href="../../dc/d84/group__core__basic.html#ga346f563897249351a34549137c8532a0">Size</a>( 640, 480 ), 0, 0, <a class="code" href="../../da/d54/group__imgproc__transform.html#gga5bb5a1fea74ea38e1a5445ca803ff121ac00f4a8155563cdc23437fc0959da935">INTER_LINEAR_EXACT</a> );</div><div class="line">    <a class="code" href="../../d7/dfc/group__highgui.html#ga453d42fe4cb60e5723281a89973ee563">imshow</a>( <span class="stringliteral">&quot;threshold disp otsu&quot;</span>, dst );</div><div class="line"></div><div class="line"><span class="preprocessor">#ifdef HAVE_OPENCV_VIZ</span></div><div class="line">    <span class="comment">// Apply the mask to the point cloud</span></div><div class="line">    <a class="code" href="../../d3/d63/classcv_1_1Mat.html">Mat</a> pointcloud_tresh, color_tresh;</div><div class="line">    pointcloud.<a class="code" href="../../d3/d63/classcv_1_1Mat.html#a33fd5d125b4c302b0c9aa86980791a77">copyTo</a>( pointcloud_tresh, thresholded_disp );</div><div class="line">    color.<a class="code" href="../../d3/d63/classcv_1_1Mat.html#a33fd5d125b4c302b0c9aa86980791a77">copyTo</a>( color_tresh, thresholded_disp );</div><div class="line"></div><div class="line">    <span class="comment">// Show the point cloud on viz</span></div><div class="line">    <a class="code" href="../../d6/d32/classcv_1_1viz_1_1Viz3d.html">viz::Viz3d</a> myWindow( <span class="stringliteral">&quot;Point cloud with color&quot;</span> );</div><div class="line">    myWindow.setBackgroundMeshLab();</div><div class="line">    myWindow.showWidget( <span class="stringliteral">&quot;coosys&quot;</span>, <a class="code" href="../../df/d63/classcv_1_1viz_1_1WCoordinateSystem.html">viz::WCoordinateSystem</a>() );</div><div class="line">    myWindow.showWidget( <span class="stringliteral">&quot;pointcloud&quot;</span>, <a class="code" href="../../db/d82/classcv_1_1viz_1_1WCloud.html">viz::WCloud</a>( pointcloud_tresh, color_tresh ) );</div><div class="line">    myWindow.showWidget( <span class="stringliteral">&quot;text2d&quot;</span>, <a class="code" href="../../de/d0b/classcv_1_1viz_1_1WText.html">viz::WText</a>( <span class="stringliteral">&quot;Point cloud&quot;</span>, <a class="code" href="../../dc/d84/group__core__basic.html#ga1e83eafb2d26b3c93f09e8338bcab192">Point</a>(20, 20), 20, viz::Color::green() ) );</div><div class="line">    myWindow.spin();</div><div class="line"><span class="preprocessor">#endif // HAVE_OPENCV_VIZ</span></div><div class="line"></div><div class="line">  }</div><div class="line"></div><div class="line">  <a class="code" href="../../d7/dfc/group__highgui.html#ga5628525ad33f52eab17feebcfba38bd7">waitKey</a>();</div><div class="line">  <span class="keywordflow">return</span> 0;</div><div class="line">}</div></div><!-- fragment --><h2>Explanation </h2>
<p>First of all the needed parameters must be passed to the program. The first is the name list of previously acquired pattern images, stored in a .yaml file organized as below:</p>
<div class="fragment"><div class="line">%YAML:1.0</div><div class="line">cam1:</div><div class="line">   - <span class="stringliteral">&quot;/data/pattern_cam1_im1.png&quot;</span></div><div class="line">   - <span class="stringliteral">&quot;/data/pattern_cam1_im2.png&quot;</span></div><div class="line">           ..............</div><div class="line">   - <span class="stringliteral">&quot;/data/pattern_cam1_im42.png&quot;</span></div><div class="line">   - <span class="stringliteral">&quot;/data/pattern_cam1_im43.png&quot;</span></div><div class="line">   - <span class="stringliteral">&quot;/data/pattern_cam1_im44.png&quot;</span></div><div class="line">cam2:</div><div class="line">   - <span class="stringliteral">&quot;/data/pattern_cam2_im1.png&quot;</span></div><div class="line">   - <span class="stringliteral">&quot;/data/pattern_cam2_im2.png&quot;</span></div><div class="line">           ..............</div><div class="line">   - <span class="stringliteral">&quot;/data/pattern_cam2_im42.png&quot;</span></div><div class="line">   - <span class="stringliteral">&quot;/data/pattern_cam2_im43.png&quot;</span></div><div class="line">   - <span class="stringliteral">&quot;/data/pattern_cam2_im44.png&quot;</span></div></div><!-- fragment --><p>For example, the dataset used for this tutorial has been acquired using a projector with a resolution of 1280x800, so 42 pattern images (from number 1 to 42) + 1 white (number 43) and 1 black (number 44) were captured with both the two cameras.</p>
<p>Then the cameras calibration parameters, stored in another .yml file, together with the width and the height of the projector used to project the pattern, and, optionally, the values of white and black tresholds, must be passed to the tutorial program.</p>
<p>In this way, <em>GrayCodePattern</em> class parameters can be set up with the width and the height of the projector used during the pattern acquisition and a pointer to a GrayCodePattern object can be created:</p>
<div class="fragment"><div class="line"><a class="code" href="../../d4/d41/namespacecv_1_1dynafu.html#afe352b7045bf5f1496c2d8dd2a09a764">structured_light::GrayCodePattern::Params</a> <a class="code" href="../../d1/dae/namespacecv_1_1gapi_1_1ie.html#a3ab1729bcaf2d08e30dd2bc645410908">params</a>;</div><div class="line">   ....</div><div class="line">params.width = parser.get&lt;<span class="keywordtype">int</span>&gt;( 2 );</div><div class="line">params.height = parser.get&lt;<span class="keywordtype">int</span>&gt;( 3 );</div><div class="line">   ....</div><div class="line"><span class="comment">// Set up GraycodePattern with params</span></div><div class="line">Ptr&lt;structured_light::GrayCodePattern&gt; graycode = structured_light::GrayCodePattern::create( params );</div></div><!-- fragment --><p>If the white and black thresholds are passed as parameters (these thresholds influence the number of decoded pixels), their values can be set, otherwise the algorithm will use the default values.</p>
<div class="fragment"><div class="line"><span class="keywordtype">size_t</span> white_thresh = 0;</div><div class="line"><span class="keywordtype">size_t</span> black_thresh = 0;</div><div class="line"><span class="keywordflow">if</span>( argc == 7 )</div><div class="line">{</div><div class="line">  <span class="comment">// If passed, setting the white and black threshold, otherwise using default values</span></div><div class="line">  white_thresh = parser.get&lt;<span class="keywordtype">size_t</span>&gt;( 4 );</div><div class="line">  black_thresh = parser.get&lt;<span class="keywordtype">size_t</span>&gt;( 5 );</div><div class="line">  graycode-&gt;setWhiteThreshold( white_thresh );</div><div class="line">  graycode-&gt;setBlackThreshold( black_thresh );</div><div class="line">}</div></div><!-- fragment --><p>At this point, to use the <em>decode</em> method of <em>GrayCodePattern</em> class, the acquired pattern images must be stored in a vector of vector of Mat. The external vector has a size of two because two are the cameras: the first vector stores the pattern images captured from the left camera, the second those acquired from the right one. The number of pattern images is obviously the same for both cameras and can be retrieved using the getNumberOfPatternImages() method:</p>
<div class="fragment"><div class="line"><span class="keywordtype">size_t</span> numberOfPatternImages = graycode-&gt;getNumberOfPatternImages();</div><div class="line">vector&lt;vector&lt;Mat&gt; &gt; captured_pattern;</div><div class="line">captured_pattern.resize( 2 );</div><div class="line">captured_pattern[0].resize( numberOfPatternImages );</div><div class="line">captured_pattern[1].resize( numberOfPatternImages );</div><div class="line"></div><div class="line">.....</div><div class="line"></div><div class="line">for( <span class="keywordtype">size_t</span> i = 0; i &lt; numberOfPatternImages; i++ )</div><div class="line">{</div><div class="line">  captured_pattern[0][i] = <a class="code" href="../../d4/da8/group__imgcodecs.html#ga288b8b3da0892bd651fce07b3bbd3a56">imread</a>( imagelist[i], <a class="code" href="../../d8/d6a/group__imgcodecs__flags.html#gga61d9b0126a3e57d9277ac48327799c80ae29981cfc153d3b0cef5c0daeedd2125">IMREAD_GRAYSCALE</a> );</div><div class="line">  captured_pattern[1][i] = <a class="code" href="../../d4/da8/group__imgcodecs.html#ga288b8b3da0892bd651fce07b3bbd3a56">imread</a>( imagelist[i + numberOfPatternImages + 2], <a class="code" href="../../d8/d6a/group__imgcodecs__flags.html#gga61d9b0126a3e57d9277ac48327799c80ae29981cfc153d3b0cef5c0daeedd2125">IMREAD_GRAYSCALE</a> );</div><div class="line">   ......</div><div class="line">}</div></div><!-- fragment --><p>As regards the black and white images, they must be stored in two different vectors of Mat:</p>
<div class="fragment"><div class="line">vector&lt;Mat&gt; blackImages;</div><div class="line">vector&lt;Mat&gt; whiteImages;</div><div class="line">blackImages.resize( 2 );</div><div class="line">whiteImages.resize( 2 );</div><div class="line"><span class="comment">// Loading images (all white + all black) needed for shadows computation</span></div><div class="line"><a class="code" href="../../d8/d01/group__imgproc__color__conversions.html#ga397ae87e1288a81d2363b61574eb8cab">cvtColor</a>( color, whiteImages[0], <a class="code" href="../../d8/d01/group__imgproc__color__conversions.html#gga4e0972be5de079fed4e3a10e24ef5ef0ae50d0c66ee53e974234ac84cf51d1d4e">COLOR_RGB2GRAY</a> );</div><div class="line">whiteImages[1] = <a class="code" href="../../d4/da8/group__imgcodecs.html#ga288b8b3da0892bd651fce07b3bbd3a56">imread</a>( imagelist[2 * numberOfPatternImages + 2], <a class="code" href="../../d8/d6a/group__imgcodecs__flags.html#gga61d9b0126a3e57d9277ac48327799c80ae29981cfc153d3b0cef5c0daeedd2125">IMREAD_GRAYSCALE</a> );</div><div class="line">blackImages[0] = <a class="code" href="../../d4/da8/group__imgcodecs.html#ga288b8b3da0892bd651fce07b3bbd3a56">imread</a>( imagelist[numberOfPatternImages + 1], <a class="code" href="../../d8/d6a/group__imgcodecs__flags.html#gga61d9b0126a3e57d9277ac48327799c80ae29981cfc153d3b0cef5c0daeedd2125">IMREAD_GRAYSCALE</a> );</div><div class="line">blackImages[1] = <a class="code" href="../../d4/da8/group__imgcodecs.html#ga288b8b3da0892bd651fce07b3bbd3a56">imread</a>( imagelist[2 * numberOfPatternImages + 2 + 1], <a class="code" href="../../d8/d6a/group__imgcodecs__flags.html#gga61d9b0126a3e57d9277ac48327799c80ae29981cfc153d3b0cef5c0daeedd2125">IMREAD_GRAYSCALE</a> );</div></div><!-- fragment --><p>It is important to underline that all the images, the pattern ones, black and white, must be loaded as grayscale images and rectified before being passed to decode method:</p>
<div class="fragment"><div class="line"><span class="comment">// Stereo rectify</span></div><div class="line">cout &lt;&lt; <span class="stringliteral">&quot;Rectifying images...&quot;</span> &lt;&lt; endl;</div><div class="line">Mat R1, R2, P1, P2, Q;</div><div class="line"><a class="code" href="../../dc/d84/group__core__basic.html#ga11d95de507098e90bad732b9345402e8">Rect</a> validRoi[2];</div><div class="line"><a class="code" href="../../d9/d0c/group__calib3d.html#ga617b1685d4059c6040827800e72ad2b6">stereoRectify</a>( cam1intrinsics, cam1distCoeffs, cam2intrinsics, cam2distCoeffs, imagesSize, R, T, R1, R2, P1, P2, Q, 0,</div><div class="line">              -1, imagesSize, &amp;validRoi[0], &amp;validRoi[1] );</div><div class="line">Mat map1x, map1y, map2x, map2y;</div><div class="line"><a class="code" href="../../d9/d0c/group__calib3d.html#ga7dfb72c9cf9780a347fbe3d1c47e5d5a">initUndistortRectifyMap</a>( cam1intrinsics, cam1distCoeffs, R1, P1, imagesSize, <a class="code" href="../../d1/d1b/group__core__hal__interface.html#ga32ec76240e43e4c9c7b2e2785180a7e6">CV_32FC1</a>, map1x, map1y );</div><div class="line"><a class="code" href="../../d9/d0c/group__calib3d.html#ga7dfb72c9cf9780a347fbe3d1c47e5d5a">initUndistortRectifyMap</a>( cam2intrinsics, cam2distCoeffs, R2, P2, imagesSize, <a class="code" href="../../d1/d1b/group__core__hal__interface.html#ga32ec76240e43e4c9c7b2e2785180a7e6">CV_32FC1</a>, map2x, map2y );</div><div class="line">       ........</div><div class="line"><span class="keywordflow">for</span>( <span class="keywordtype">size_t</span> i = 0; i &lt; numberOfPatternImages; i++ )</div><div class="line">{</div><div class="line">       ........</div><div class="line">  <a class="code" href="../../da/d54/group__imgproc__transform.html#gab75ef31ce5cdfb5c44b6da5f3b908ea4">remap</a>( captured_pattern[1][i], captured_pattern[1][i], map1x, map1y, <a class="code" href="../../da/d54/group__imgproc__transform.html#gga5bb5a1fea74ea38e1a5445ca803ff121aa5521d8e080972c762467c45f3b70e6c">INTER_NEAREST</a>, <a class="code" href="../../d2/de8/group__core__array.html#gga209f2f4869e304c82d07739337eae7c5aed2e4346047e265c8c5a6d0276dcd838">BORDER_CONSTANT</a>, <a class="code" href="../../dc/d84/group__core__basic.html#ga599fe92e910c027be274233eccad7beb">Scalar</a>() );</div><div class="line">  <a class="code" href="../../da/d54/group__imgproc__transform.html#gab75ef31ce5cdfb5c44b6da5f3b908ea4">remap</a>( captured_pattern[0][i], captured_pattern[0][i], map2x, map2y, <a class="code" href="../../da/d54/group__imgproc__transform.html#gga5bb5a1fea74ea38e1a5445ca803ff121aa5521d8e080972c762467c45f3b70e6c">INTER_NEAREST</a>, <a class="code" href="../../d2/de8/group__core__array.html#gga209f2f4869e304c82d07739337eae7c5aed2e4346047e265c8c5a6d0276dcd838">BORDER_CONSTANT</a>, <a class="code" href="../../dc/d84/group__core__basic.html#ga599fe92e910c027be274233eccad7beb">Scalar</a>() );</div><div class="line">}</div><div class="line">       ........</div><div class="line"><a class="code" href="../../da/d54/group__imgproc__transform.html#gab75ef31ce5cdfb5c44b6da5f3b908ea4">remap</a>( color, color, map2x, map2y, <a class="code" href="../../da/d54/group__imgproc__transform.html#gga5bb5a1fea74ea38e1a5445ca803ff121aa5521d8e080972c762467c45f3b70e6c">INTER_NEAREST</a>, <a class="code" href="../../d2/de8/group__core__array.html#gga209f2f4869e304c82d07739337eae7c5aed2e4346047e265c8c5a6d0276dcd838">BORDER_CONSTANT</a>, <a class="code" href="../../dc/d84/group__core__basic.html#ga599fe92e910c027be274233eccad7beb">Scalar</a>() );</div><div class="line"><a class="code" href="../../da/d54/group__imgproc__transform.html#gab75ef31ce5cdfb5c44b6da5f3b908ea4">remap</a>( whiteImages[0], whiteImages[0], map2x, map2y, <a class="code" href="../../da/d54/group__imgproc__transform.html#gga5bb5a1fea74ea38e1a5445ca803ff121aa5521d8e080972c762467c45f3b70e6c">INTER_NEAREST</a>, <a class="code" href="../../d2/de8/group__core__array.html#gga209f2f4869e304c82d07739337eae7c5aed2e4346047e265c8c5a6d0276dcd838">BORDER_CONSTANT</a>, <a class="code" href="../../dc/d84/group__core__basic.html#ga599fe92e910c027be274233eccad7beb">Scalar</a>() );</div><div class="line"><a class="code" href="../../da/d54/group__imgproc__transform.html#gab75ef31ce5cdfb5c44b6da5f3b908ea4">remap</a>( whiteImages[1], whiteImages[1], map1x, map1y, <a class="code" href="../../da/d54/group__imgproc__transform.html#gga5bb5a1fea74ea38e1a5445ca803ff121aa5521d8e080972c762467c45f3b70e6c">INTER_NEAREST</a>, <a class="code" href="../../d2/de8/group__core__array.html#gga209f2f4869e304c82d07739337eae7c5aed2e4346047e265c8c5a6d0276dcd838">BORDER_CONSTANT</a>, <a class="code" href="../../dc/d84/group__core__basic.html#ga599fe92e910c027be274233eccad7beb">Scalar</a>() );</div><div class="line"><a class="code" href="../../da/d54/group__imgproc__transform.html#gab75ef31ce5cdfb5c44b6da5f3b908ea4">remap</a>( blackImages[0], blackImages[0], map2x, map2y, <a class="code" href="../../da/d54/group__imgproc__transform.html#gga5bb5a1fea74ea38e1a5445ca803ff121aa5521d8e080972c762467c45f3b70e6c">INTER_NEAREST</a>, <a class="code" href="../../d2/de8/group__core__array.html#gga209f2f4869e304c82d07739337eae7c5aed2e4346047e265c8c5a6d0276dcd838">BORDER_CONSTANT</a>, <a class="code" href="../../dc/d84/group__core__basic.html#ga599fe92e910c027be274233eccad7beb">Scalar</a>() );</div><div class="line"><a class="code" href="../../da/d54/group__imgproc__transform.html#gab75ef31ce5cdfb5c44b6da5f3b908ea4">remap</a>( blackImages[1], blackImages[1], map1x, map1y, <a class="code" href="../../da/d54/group__imgproc__transform.html#gga5bb5a1fea74ea38e1a5445ca803ff121aa5521d8e080972c762467c45f3b70e6c">INTER_NEAREST</a>, <a class="code" href="../../d2/de8/group__core__array.html#gga209f2f4869e304c82d07739337eae7c5aed2e4346047e265c8c5a6d0276dcd838">BORDER_CONSTANT</a>, <a class="code" href="../../dc/d84/group__core__basic.html#ga599fe92e910c027be274233eccad7beb">Scalar</a>() );</div></div><!-- fragment --><p>In this way the <em>decode</em> method can be called to decode the pattern and to generate the corresponding disparity map, computed on the first camera (left): </p><div class="fragment"><div class="line">Mat disparityMap;</div><div class="line"><span class="keywordtype">bool</span> decoded = graycode-&gt;decode(captured_pattern, disparityMap, blackImages, whiteImages,</div><div class="line">                                <a class="code" href="../../d1/d90/group__structured__light.html#ggafaa062a39adfeb3836b8730fda1a6b89a98f0a8c890dded38d226722bcdd5795c">structured_light::DECODE_3D_UNDERWORLD</a>);</div></div><!-- fragment --><p>To better visualize the result, a colormap is applied to the computed disparity: </p><div class="fragment"><div class="line"><span class="keywordtype">double</span> <a class="code" href="../../d1/d10/classcv_1_1MatExpr.html#ac22d7d32f1ec91fd106760a98a6f4731">min</a>;</div><div class="line"><span class="keywordtype">double</span> <a class="code" href="../../d1/d10/classcv_1_1MatExpr.html#a6dff8b6e9105b6d817b493e7be157c90">max</a>;</div><div class="line"><a class="code" href="../../d2/de8/group__core__array.html#ga7622c466c628a75d9ed008b42250a73f">minMaxIdx</a>(disparityMap, &amp;min, &amp;max);</div><div class="line">Mat cm_disp, scaledDisparityMap;</div><div class="line">cout &lt;&lt; <span class="stringliteral">&quot;disp min &quot;</span> &lt;&lt; min &lt;&lt; endl &lt;&lt; <span class="stringliteral">&quot;disp max &quot;</span> &lt;&lt; max &lt;&lt; endl;</div><div class="line"><a class="code" href="../../d2/de8/group__core__array.html#ga3460e9c9f37b563ab9dd550c4d8c4e7d">convertScaleAbs</a>( disparityMap, scaledDisparityMap, 255 / ( max - min ) );</div><div class="line"><a class="code" href="../../d3/d50/group__imgproc__colormap.html#gadf478a5e5ff49d8aa24e726ea6f65d15">applyColorMap</a>( scaledDisparityMap, cm_disp, <a class="code" href="../../d3/d50/group__imgproc__colormap.html#gga9a805d8262bcbe273f16be9ea2055a65ab3f207661ddf74511b002b1acda5ec09">COLORMAP_JET</a> );</div><div class="line"><span class="comment">// Show the result</span></div><div class="line"><a class="code" href="../../d5/df1/group__imgproc__hal__functions.html#ga2fe39d2201b12e1b961ca56b2aff9ff2">resize</a>( cm_disp, cm_disp, <a class="code" href="../../dc/d84/group__core__basic.html#ga346f563897249351a34549137c8532a0">Size</a>( 640, 480 ) );</div><div class="line"><a class="code" href="../../d7/dfc/group__highgui.html#ga453d42fe4cb60e5723281a89973ee563">imshow</a>( <span class="stringliteral">&quot;cm disparity m&quot;</span>, cm_disp )</div></div><!-- fragment --><div class="image">
<img src="../../cm_disparity.png" alt="cm_disparity.png"/>
</div>
<p>At this point the point cloud can be generated using the reprojectImageTo3D method, taking care to convert the computed disparity in a CV_32FC1 Mat (decode method computes a CV_64FC1 disparity map): </p><div class="fragment"><div class="line">Mat pointcloud;</div><div class="line">disparityMap.<a class="code" href="../../d3/d63/classcv_1_1Mat.html#adf88c60c5b4980e05bb556080916978b">convertTo</a>( disparityMap, <a class="code" href="../../d1/d1b/group__core__hal__interface.html#ga32ec76240e43e4c9c7b2e2785180a7e6">CV_32FC1</a> );</div><div class="line"><a class="code" href="../../d9/d0c/group__calib3d.html#ga1bc1152bd57d63bc524204f21fde6e02">reprojectImageTo3D</a>( disparityMap, pointcloud, Q, <span class="keyword">true</span>, -1 );</div></div><!-- fragment --><p>Then a mask to remove the unwanted background is computed: </p><div class="fragment"><div class="line">Mat dst, thresholded_disp;</div><div class="line"><a class="code" href="../../d7/d1b/group__imgproc__misc.html#gae8a4a146d1ca78c626a53577199e9c57">threshold</a>( scaledDisparityMap, thresholded_disp, 0, 255, <a class="code" href="../../d7/d1b/group__imgproc__misc.html#ggaa9e58d2860d4afa658ef70a9b1115576a95251923e8e22f368ffa86ba8bce87ff">THRESH_OTSU</a> + <a class="code" href="../../d7/d1b/group__imgproc__misc.html#ggaa9e58d2860d4afa658ef70a9b1115576a147222a96556ebc1d948b372bcd7ac59">THRESH_BINARY</a> );</div><div class="line"><a class="code" href="../../d5/df1/group__imgproc__hal__functions.html#ga2fe39d2201b12e1b961ca56b2aff9ff2">resize</a>( thresholded_disp, dst, <a class="code" href="../../dc/d84/group__core__basic.html#ga346f563897249351a34549137c8532a0">Size</a>( 640, 480 ) );</div><div class="line"><a class="code" href="../../d7/dfc/group__highgui.html#ga453d42fe4cb60e5723281a89973ee563">imshow</a>( <span class="stringliteral">&quot;threshold disp otsu&quot;</span>, dst );</div></div><!-- fragment --> <div class="image">
<img src="../../threshold_disp.png" alt="threshold_disp.png"/>
</div>
<p>The white image of cam1 was previously loaded also as a color image, in order to map the color of the object on its reconstructed pointcloud: </p><div class="fragment"><div class="line">Mat color = <a class="code" href="../../d4/da8/group__imgcodecs.html#ga288b8b3da0892bd651fce07b3bbd3a56">imread</a>( imagelist[numberOfPatternImages], <a class="code" href="../../d8/d6a/group__imgcodecs__flags.html#gga61d9b0126a3e57d9277ac48327799c80af660544735200cbe942eea09232eb822">IMREAD_COLOR</a> );</div></div><!-- fragment --><p>The background renoval mask is thus applied to the point cloud and to the color image: </p><div class="fragment"><div class="line">Mat pointcloud_tresh, color_tresh;</div><div class="line">pointcloud.<a class="code" href="../../d3/d63/classcv_1_1Mat.html#a33fd5d125b4c302b0c9aa86980791a77">copyTo</a>(pointcloud_tresh, thresholded_disp);</div><div class="line">color.copyTo(color_tresh, thresholded_disp);</div></div><!-- fragment --><p>Finally the computed point cloud of the scanned object can be visualized on viz: </p><div class="fragment"><div class="line">viz::Viz3d myWindow( <span class="stringliteral">&quot;Point cloud with color&quot;</span>);</div><div class="line">myWindow.setBackgroundMeshLab();</div><div class="line">myWindow.showWidget( <span class="stringliteral">&quot;coosys&quot;</span>, viz::WCoordinateSystem());</div><div class="line">myWindow.showWidget( <span class="stringliteral">&quot;pointcloud&quot;</span>, viz::WCloud( pointcloud_tresh, color_tresh ) );</div><div class="line">myWindow.showWidget( <span class="stringliteral">&quot;text2d&quot;</span>, viz::WText( <span class="stringliteral">&quot;Point cloud&quot;</span>, <a class="code" href="../../dc/d84/group__core__basic.html#ga1e83eafb2d26b3c93f09e8338bcab192">Point</a>(20, 20), 20, viz::Color::green() ) );</div><div class="line">myWindow.spin();</div></div><!-- fragment --><div class="image">
<img src="../../plane_viz.png" alt="plane_viz.png"/>
</div>
 </div></div><!-- contents -->
<!-- HTML footer for doxygen 1.8.6-->
<!-- start footer part -->
<hr class="footer"/><address class="footer"><small>
Generated on Fri Apr 2 2021 11:36:39 for OpenCV by &#160;<a href="http://www.doxygen.org/index.html">
<img class="footer" src="../../doxygen.png" alt="doxygen"/>
</a> 1.8.13
</small></address>
<script type="text/javascript">
//<![CDATA[
addTutorialsButtons();
//]]>
</script>
</body>
</html>
